package com.eric.statemachinedemo.service;

import com.eric.statemachinedemo.config.RmaStateMachineConfig;
import com.eric.statemachinedemo.constant.ResponseCodeEnum;
import com.eric.statemachinedemo.constant.RmaEventEnum;
import com.eric.statemachinedemo.constant.RmaStatusEnum;
import com.eric.statemachinedemo.exception.ProcessExceptionCast;
import com.eric.statemachinedemo.model.request.ProcessRequestData;
import com.eric.statemachinedemo.model.response.ResponseResult;
import com.eric.statemachinedemo.strategy.RmaProcessExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Service;

import java.util.UUID;

@Service
public class RmaProcessService {
    @Autowired
    private StateMachineFactory<RmaStatusEnum, RmaEventEnum> rmaStateMachineFactory;

    @Autowired
    private StateMachinePersister<RmaStatusEnum, RmaEventEnum, String> rmaStateMachinePersist;


    @Autowired
    private RmaProcessExecutor processExecutor;
    //开单
    public ResponseResult createRma(){
        String businessKey = UUID.randomUUID().toString();
        //取状态机
        StateMachine<RmaStatusEnum, RmaEventEnum> stateMachine = rmaStateMachineFactory.getStateMachine(RmaStateMachineConfig.MACHINE_ID);
        stateMachine.start();
        //持久化
        try {
            rmaStateMachinePersist.persist(stateMachine, businessKey);
        } catch (Exception e) {
            ProcessExceptionCast.cast(ResponseCodeEnum.SERVER_ERROR);
        }
        return new ResponseResult(ResponseCodeEnum.START_PROCESS, businessKey);
    }

    //下一步
    public ResponseResult nextStep(ProcessRequestData requestData){

        //1.取当前状态，做校验(以KEYIN为例)
        RmaStatusEnum status = RmaStatusEnum.valueOf("KEYIN");

        //2.取状态机，得到当前单子的状态
        StateMachine<RmaStatusEnum, RmaEventEnum> stateMachine = rmaStateMachineFactory.getStateMachine(RmaStateMachineConfig.MACHINE_ID);
        try {
            rmaStateMachinePersist.restore(stateMachine, requestData.getBusinessKey());
        } catch (Exception e) {
            ProcessExceptionCast.cast(ResponseCodeEnum.SERVER_ERROR);
        }

        //3.查询获取下一个状态，用于得到对应的事件(以KEYIN到repair为例)
        RmaEventEnum rmaEventEnum = RmaEventEnum.EVENT_KEYIN2REPAIR;

        //4. 编辑、发送事件
        Message<RmaEventEnum> message = MessageBuilder.withPayload(rmaEventEnum).setHeader("processRequestData", requestData).build();
        boolean success = stateMachine.sendEvent(message);
        //如果当前状态与存储的状态机状态不一致（类似于双窗口），那么false
        if(!success || stateMachine.hasStateMachineError()){
            return new ResponseResult(ResponseCodeEnum.STATE_OUTDATED, requestData.getBusinessKey());
        }
        //5.持久化,保存当前单子状态机的最新状态
        try {
            rmaStateMachinePersist.persist(stateMachine, requestData.getBusinessKey());
        } catch (Exception e) {
            ProcessExceptionCast.cast(ResponseCodeEnum.SERVER_ERROR);
        }
        //返回执行成功
        return new ResponseResult(ResponseCodeEnum.COMPLETE);
    }

}
